import { routerRedux } from 'dva/router'
import { Modal, message } from 'antd'
import isObject from 'lodash/isObject'
import { forEach, isFunction } from 'lodash'
import config from '../../config/config'
import mapping, {
  changeRole,
  checkLogin,
  getVcodeFlag,
  login,
  logout,
  ssoLogin,
  unlock,
} from '@/services/login'
import {
  getItem,
  getPageQuery,
  getViewMode,
  setItem,
  storageClear,
} from '@/utils/utils'
import { reloadAuthorized } from '@/utils/Authorized'
import { setAuthority } from '@/utils/authority'
import { enableWatermark, loginRedirect, visitor } from '@/defaultSettings'
import watermark from '@/utils/waterMark'
import userInfo from '@/userInfo'
import { getUserInfo, removeUserInfo, setCurrentTenantId, setUserInfo } from '@/utils/user'
import { TAB_CLOSE_CALLBACKS } from '@/layouts/BasicLayout'

const initState = {
  status: mapping.LOG_OUT,
  user: null,
  mode: 'password', // password:密码方式登录; sms: 短信验证码方式登录; qr: 扫二维码登陆
  needVerifyCode: false, // 决定是否追加输入验证码
  isRemenber: false, // 是否记住密码
  forceLogin: false, // 23点之后需要强制才可以登录
  needModifyPsw: false, // 初始化密码需要修改后才能登陆
  verifyCode: null,
  isLogin: false,
  hasCheckedLogin: false,
}

function isOk(response) {
  return new Promise((resolve, reject) => {
    Modal.confirm({
      title: '现在为非工作时间，确定要登录系统吗?',
      content: `工作时间为：${response.resultMsg}`,
      onOk() {
        resolve(true)
      },
      onCancel() {
        // eslint-disable-next-line prefer-promise-reject-errors
        reject(false)
      },
    })
  })
}

function needModifyPsw() {
  return new Promise((resolve, reject) => {
    Modal.confirm({
      title: '初始密码需要修改后才能登录',
      content: '确定现在修改吗?',
      onOk() {
        resolve(true)
      },
      onCancel() {
        // eslint-disable-next-line prefer-promise-reject-errors
        reject(false)
      },
    })
  })
}

/**
 * 更新session数据，以及刷新权限
 * @param {object} obj
 */
function handle(obj) {
  /**
   * 提取数组中每一项的sysRoleCode
   * 清空sessionStorage，并记录当前用户信息
   * request中根据这个字段判断session失效并拦截
   *
   */
  const sysRoleCodes = []
  if (Array.isArray(obj.portalRoles)) {
    obj.portalRoles.forEach((item) => {
      if (item.sysRoleCode !== undefined)
        sysRoleCodes.push(item.sysRoleCode)
    })
  }
  storageClear()
  setItem('user', obj)
  setItem('status', mapping.LOGINED)
  setAuthority(sysRoleCodes)
  // 刷新权限组件
  reloadAuthorized()
}

function getPathname(history) {
  const urlParams = new URL(window.location.href)
  const { pathname, hash } = urlParams
  let result = '/'
  if (history === 'hash' && hash !== '')
    result = hash.slice(1)

  if (history === 'brower' && pathname !== '')
    result = pathname

  // 如果是登录页，直接进到首页
  if (result.startsWith('/user'))
    result = '/'

  return result
}

export default {
  namespace: 'login',

  state: {
    status: visitor === true ? mapping.LOGINED : mapping.CONFIRMING, //  'CONFIRMING','LOG_OUT','LOGINED','SESSION_TIME_OUT', 'LOCKED'
    user: visitor === true ? userInfo : getItem('user'),
  },

  effects: {
    *checkLogin(_, { call, put }) {
      try {
        yield call(checkLogin)
        const user = getUserInfo()
        if (user !== null) {
          setCurrentTenantId(user.defaultTenantId)
          yield put({
            type: 'update',
            payload: {
              isLogin: true,
            },
          })
        }
      }
      catch (e) {
        removeUserInfo()
      }

      yield put({
        type: 'update',
        payload: {
          hasCheckedLogin: true,
        },
      })
      // const { resultCode, ...rest } = response;
      // /**
      //  * 1、先通过logged.do接口查询是否已登录，resultCode=='0000'表示已登录（且预期回参与login.do成功登录时一致）
      //  * 2、若已登录需进一步查询是否是锁屏或超时
      //  */
      // if (`${resultCode}` === mapping.SUCC_CODE) {
      //   const resp = yield call(status, moment().format('YYYY-MM-DD HH:mm:ss'));
      //   // 登录超时或被管理员强制下线
      //   if (resp.sessionTimeout === true) {
      //     // LoginInfo.timeoutFlag = true;
      //     if (!resp.invalidateMsg) {
      //       resp.invalidateMsg = '登录会话超时';
      //     }
      //     Modal.warning({
      //       title: '提醒',
      //       content: `${resp.invalidateMsg}，请重新登录`,
      //     });
      //     yield put({
      //       type: 'logout',
      //     });
      //   } else if (resp.lockFlag === true) {
      //     yield put({
      //       type: 'lock',
      //       payload: { user: rest },
      //     });
      //   } else {
      //     const sw = traceLogAction.newStopwatch();
      //     /**
      //      * 登录成功记录登录日志
      //      */
      //     traceLogAction.traceLoginInfo({
      //       operDuration: sw.duration(),
      //     });

      //     /**
      //      * 更新model中的user和status
      //      * 重置initState中的字段，为了保证下次登陆初始化状态
      //      */
      //     yield put({
      //       type: 'loginSuccess',
      //       payload: { ...rest, status: mapping.LOGINED, initState },
      //     });

      //     // 更新session
      //     handle(rest);
      //     yield put({
      //       type: 'redirect',
      //     });
      //   }
      // } else {
      //   yield put({
      //     type: 'update',
      //     payload: { status: mapping.LOG_OUT },
      //   });
      // }
    },

    *getInitData({ payload }, { call, put }) {
      const response = yield call(getVcodeFlag, payload)
      yield put({
        type: 'needVerifyCode',
        payload: response,
      })
    },

    *login({ payload }, { call, put }) {
      try {
        const { admin, multiTenant, username, userId, defaultTenantId } = yield call(
          login,
          payload,
        )
        message.success('登录成功')
        setUserInfo({
          userId,
          username,
          isAdmin: admin,
          isMultiTenant: multiTenant,
          defaultTenantId,
        })
        setCurrentTenantId(defaultTenantId)

        yield put({
          type: 'update',
          payload: {
            isLogin: true,
          },
        })
        yield put(routerRedux.push({ pathname: '/' }))
      }
      catch (e) {
        console.log(e)
      }
      // if (response === null) {
      //   return;
      // }
      // // Login successfully
      // if (`${response.resultCode}` === mapping.SUCC_CODE) {
      //   const { resultCode, ...rest } = response;
      //   /**
      //    * 登录成功记录登录日志
      //    */
      //   traceLogAction.traceLoginInfo({
      //     operDuration: sw.duration(),
      //   });

      //   /**
      //    * 更新model中的user和status
      //    * 重置initState中的字段，为了保证下次登陆初始化状态
      //    */
      //   yield put({
      //     type: 'loginSuccess',
      //     payload: { ...rest, status: mapping.LOGINED, initState },
      //   });

      //   // 更新session
      //   handle(rest);
      //   yield put({
      //     type: 'redirect',
      //   });
      // } else if (`${response.resultCode}` === mapping.LOGIN_ERROR_NON_WORK_HOUR) {
      //   // 非工作时间登陆
      //   yield put({
      //     type: 'confirm',
      //     payload: response,
      //   });
      // } else if (`${response.resultCode}` === mapping.LOGIN_ERROR_DEFAULT_PWD) {
      //   // 初始密码需要修改后才能登录
      //   yield put({
      //     type: 'confirm2',
      //     payload: response,
      //   });
      // } else {
      //   /**
      //    * 打开验证码
      //    */
      //   yield put({
      //     type: 'needVerifyCode',
      //     payload: true,
      //   });
      //   yield put({
      //     type: 'addVerifyCode',
      //   });
      //   message.error(response.resultMsg);
      // }
    },
    *redirect(_, { put }) {
      /**
       * 如果location包含redirect，登陆成功后跳转到指目标页面
       */
      const urlParams = new URL(window.location.href)
      const { history } = config // 'browser','hash','memory'
      const params = getPageQuery()
      let { redirect } = params
      if (redirect) {
        const redirectUrlParams = new URL(redirect)
        if (redirectUrlParams.origin === urlParams.origin) {
          redirect = redirect.substr(urlParams.origin.length)
          if (redirect.match(/^\/.*#/))
            redirect = redirect.substr(redirect.indexOf('#') + 1)
        }
        else {
          window.location.href = redirect
          return
        }

        if (loginRedirect === true)
          yield put(routerRedux.replace(redirect))
        else
          yield put(routerRedux.replace('/'))
      }
      else {
        yield put(routerRedux.replace(getPathname(history)))
      }
    },
    *logout(_, { call, put }) {
      forEach(TAB_CLOSE_CALLBACKS, (cb) => {
        isFunction(cb) && cb()
      })
      // 通知后台用户登出
      yield call(logout)
      // 清除用户信息
      removeUserInfo()
      yield put({
        type: 'reset',
      })
      yield put({ type: 'checkLogin' })

      // // 防止重复追加redirect
      // if (window.location.href.indexOf('user/login?redirect=http') === -1) {
      //   let obj = {
      //     pathname: '/user/login',
      //   };

      //   // 重定向开关
      //   if (loginRedirect === true) {
      //     obj = {
      //       ...obj,
      //       search: stringify({
      //         redirect: window.location.href,
      //       }),
      //     };
      //   }
      //   yield put(routerRedux.push(obj));
      // }
    },

    /**
     * 角色切换
     * 1、更新当前用户信息
     * 2、更新跟角色相关的菜单信息
     * @param {number} payload 角色ID
     */
    *changeRole({ payload }, { call, put }) {
      const response = yield call(changeRole, { roleId: payload })

      if (response === null)
        return

      // Login successfully
      if (`${response.resultCode}` === mapping.SUCC_CODE) {
        const { resultCode, ...rest } = response

        /**
         * 更新model中的user和status
         * 重置initState中的字段，为了保证下次登陆初始化状态
         */
        yield put({
          type: 'loginSuccess',
          payload: { ...rest, status: mapping.LOGINED, initState },
        })

        // 更新跟角色相关的菜单信息
        yield put({
          type: 'menu/getInitData',
        })
        // 更新session
        handle(rest)
      }
      else if (response.resultMsg) {
        message.error(response.resultMsg)
      }
    },
    *confirm({ payload }, { call, put }) {
      const promise = yield call(isOk, payload)
      if (promise === true) {
        yield put({
          type: 'forceLogin',
        })
      }
    },
    *confirm2({ payload }, { call, put }) {
      const promise = yield call(needModifyPsw, payload)
      if (promise === true) {
        yield put({
          type: 'update',
          payload: {
            needModifyPsw: true,
          },
        })
      }
    },
    *unlock({ payload }, { call, put }) {
      const response = yield call(unlock, payload)
      // 初始密码也认为是解锁成功
      if (
        mapping.SUCC_CODE === response.resultCode
        || response.resultCode === mapping.LOGIN_ERROR_DEFAULT_PWD
      ) {
        yield put({
          type: 'logined',
        })
      }
      else {
        message.error(response.resultMsg)
      }
    },
    *ssoLogin({ payload }, { call, put }) {
      const response = yield call(ssoLogin, payload)
      // const { success } = response;
      // const { language } = parseQuery(window.location.href);
      // if (resultCode === '0') {
      //   // 更新session
      //   handle(resultObject);
      //   /**
      //    * - url中包含有效language则提取使用
      //    * - 不包含则默认中文
      //    * TODO: 这块设置国际化应该弱到subscriptions.setup处做监听
      //    */
      //   if (['zh-CN', 'en-US'].indexOf(language) !== -1) {
      //     setLocale(language);
      //   } else {
      //     setLocale('zh-CN');
      //   }
      //   yield put({
      //     type: 'loginSuccess',
      //     payload: { ...resultObject, status: mapping.LOGINED, initState },
      //   });
      // }
    },
    *clear(_, { put }) {
      // 擦掉session storage中的数据
      storageClear()
      reloadAuthorized()
      // 防止登录页出现水印
      if (enableWatermark)
        watermark.remove()

      yield put({
        type: 'reset',
      })
      yield put({
        type: 'menu/reset',
      })
    },
  },

  reducers: {
    reset() {
      return initState
    },
    update(state, { payload }) {
      return {
        ...state,
        ...payload,
      }
    },
    updateAvatar(state, { payload }) {
      const { avatar } = payload
      const { user } = state
      if (isObject(user.userInfo))
        user.userInfo.userPhoto = avatar

      setItem('user', user)
      return {
        ...state,
        user,
      }
    },
    loginSuccess(state, { payload }) {
      const { status, initState, ...rest } = payload
      return {
        ...state,
        ...initState,
        status,
        user: rest,
      }
    },
    needVerifyCode(state, { payload }) {
      return {
        ...state,
        needVerifyCode: payload,
      }
    },
    forceLogin(state) {
      return {
        ...state,
        forceLogin: true,
      }
    },
    sessionTimeout(state) {
      storageClear()
      return {
        ...state,
        user: null,
        status: mapping.SESSION_TIME_OUT,
      }
    },
    lock(state, { payload }) {
      setItem('status', mapping.LOCKED)
      if (payload) {
        return {
          ...state,
          status: mapping.LOCKED,
          user: payload.user,
        }
      }
      return {
        ...state,
        status: mapping.LOCKED,
      }
    },
    logined(state) {
      return {
        ...state,
        status: mapping.LOGINED,
      }
    },
    addVerifyCode(state) {
      return {
        ...state,
        verifyCode: `portal/LoginController/vcode.do?${new Date().getTime()}`,
      }
    },
    clearVerifyCode(state) {
      return {
        ...state,
        verifyCode: null,
      }
    },
  },
  subscriptions: {
    setup({ dispatch, history }) {
      return history.listen(() => {
        // 只在viewMode发生改变之后才更新
        // window.g_app._store.getState().setting取到的值表示当前的视图模式
        // TODO: 还需要监听inner模式下language的变化并通过设置setLocale促使页面刷新，改变国际化文本
        if (
          window.g_app._store.getState().setting
          && window.g_app._store.getState().setting.viewMode !== getViewMode()
        ) {
          dispatch({
            type: 'setting/updateViewMode',
            payload: {
              viewMode: getViewMode(),
            },
          })
        }
      })
    },
  },
}
